package com.example.csmall.product.controller;

import com.example.csmall.product.ex.ServiceException;
import com.example.csmall.product.web.JsonResult;
import com.example.csmall.product.web.ServiceCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;

/**
 * @RestControllerAdvice 将此类设定为全局异常处理器
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler
    public JsonResult<Void> handleServiceException(ServiceException e){
        //给客户端返回具体的错误信息，再由前端继续处理
        return JsonResult.fail(e);
    }

    /**
     * 处理@NotNull非空异常
     * @param e BindException
     * @return 获取到NotNull注解的message属性的值
     */
    @ExceptionHandler
    public String handleBindException(BindException e) {
        //获取其中一个错误信息
        //如果采取快速失败的策略，那么应该使用只拿到错误信息中的其中一个错误.
        String message = e.getFieldError().getDefaultMessage();
        return message;

//        //获取全部错误
//        List<FieldError> fieldError = e.getFieldErrors();
//        StringJoiner stringJoiner = new StringJoiner(",");
//        for (FieldError error : fieldError) {
//            stringJoiner.add(error.getDefaultMessage());
//        }
//        return stringJoiner.toString();
    }

    /**
     * 处理@Range超出约束范围异常
     * @param e ConstraintViolationException
     * @return Validation框架抛出的ConstraintViolationException异常中给出的提示信息
     */
    @ExceptionHandler
    public String handleConstraintViolationException(ConstraintViolationException e){
        //我们给出的提示信息，应该是给用户做出正确的引导信息
        //表示若干个错误
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        String message="";
        //我们配置好的快速失败也同样可以在此处触发
        for (ConstraintViolation<?> constraintViolation : constraintViolations) {
            message = constraintViolation.getMessage();
        }
        return message;
    }

    @ExceptionHandler
    public JsonResult<Void> handleThrowable(Throwable e){
        String message="服务器正忙，请稍后访问";
        log.warn("异常的名称为:{}",e.getClass().getName());
        log.warn("异常得警告信息:{}",e.getMessage());
        return JsonResult.fail(ServiceCode.ERR_UNKNOWN,message);
    }


}
